﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace MSharp.Data.SPI
{
    public interface IDB
    {
        #region AOP拦截
        Action<string, DbParameterCollection> OnExecuting { get; set; }

        Func<string, DbParameterCollection, KeyValuePair<string, DbParameter[]>> OnExecutingChange { get; set; }

        Action<string, DbParameterCollection, object> OnExecuted { get; set; }

        Action<string, DbParameterCollection, Exception> OnError { get; set; }

        #endregion

        #region Bool查询
        
        NameValueCollection GetExcludeInsertColumns();

        ExcludeColumnList ExcludeInsertColumns { get; }

        bool TryConnect();

        bool ValidateSql(string strSql, out Exception ex);


        #endregion

        #region 基础查询

        TRet Single<TRet>(string strSql, TRet defRet, int timeOut = 30);
        TRet Single<TRet, P>(string strSql, TRet defRet, P param = null, int timeOut = 30) where P : class;

        DataRow FirstRow(string strSql, int timeOut = 30);
        DataRow FirstRow<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        DataTable QueryTable(string strSql, int timeOut = 30);
        DataTable QueryTable<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        List<DataTable> QueryListTable(string strSql, int timeOut = 30);
        List<DataTable> QueryListTable<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        DataSet QueryDS(string strSql, int timeOut = 30);
        DataSet QueryDS<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        DataSet QueryDSByProc(string storedProcName, int timeOut = 30);
        DataSet QueryDSByProc<P>(string storedProcName, P param = null, int timeOut = 30) where P : class;

        DataTable QueryTableByProc(string storedProcName, int timeOut = 30);
        DataTable QueryTableByProc<P>(string storedProcName, P param = null, int timeOut = 30) where P : class;

        DbDataReader Reader(string strSql, int timeOut = 30);
        DbDataReader Reader<P>(string strSql, P param = null, int timeOut = 30) where P : class;
        TRet ReadSingle<TRet>(string strSql, TRet defRet, int timeOut = 30);
        TRet ReadSingle<TRet, P>(string strSql, TRet defRet, P param = null, int timeOut = 30) where P : class;
        Dictionary<string,object> ReadFirstRow(string strSql, int timeOut = 30);
        Dictionary<string, object> ReadFirstRow<P>(string strSql, P param = null, int timeOut = 30) where P : class;
        DataTable ReadTable(string strSql, int timeOut = 30);
        DataTable ReadTable<P>(string strSql, P param = null, int timeOut = 30) where P : class;
        
        List<TEntity> ReadEntitys<TEntity>(string strSql, Func<DbDataReader, List<TEntity>> convertTo, int timeOut = 30);

        List<TEntity> ReadEntitys<TEntity, P>(string strSql, Func<DbDataReader, List<TEntity>> convertTo, P param = null, int timeOut = 30) where P : class;

        List<TRet> ReadList<TRet>(string strSql, int timeOut = 30);

        List<TRet> ReadList<TRet, P>(string strSql, P param = null, int timeOut = 30) where P : class;

        NameValueCollection ReadNameValues(string strSql, int timeOut = 30);

        NameValueCollection ReadNameValues<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        Dictionary<TKey, TValue> ReadDictionary<TKey, TValue>(string strSql, int timeOut = 30);

        Dictionary<TKey, TValue> ReadDictionary<TKey, TValue, P>(string strSql, P param = null, int timeOut = 30) where P : class;

        #endregion

        #region 执行
        int ExecSql(string strSql, int timeOut = 30);
        int ExecSql<P>(string strSql, P param = null, int timeOut = 30) where P : class;

        int ExecSqlTran(string[] sqlCmds, int timeOut = 30);
        int ExecSqlTran(params string[] sqlCmds);
        int ExecSqlTran(List<KeyValuePair<string, List<DbParameter>>> strSqlList, int timeOut = 30);

        int ExecProc(string procName, int timeOut = 30);
        int ExecProc<P>(string procName, P param = null, int timeOut = 30) where P : class;
        
        #endregion

        #region BulkCopy
        bool BulkCopy(DataTable data, string tableName, Dictionary<string, string> columnMappings = null, int batchSize = 200000, int bulkCopyTimeout = 60);

        bool BulkCopy<P>(DataTable data, string tableName, P columnMappings = null, int batchSize = 200000, int bulkCopyTimeout = 60) where P : class;

        bool BulkCopy(DbDataReader reader, string tableName, Dictionary<string, string> columnMappings = null, int batchSize = 200000, int bulkCopyTimeout = 60);

        bool BulkCopy<P>(DbDataReader reader, string tableName, P columnMappings = null, int batchSize = 200000, int bulkCopyTimeout = 60) where P : class;

        #endregion

        #region 根据表名，列名，列相关操作

        bool ExistByColVal<P>(string tableName, string columnName, object columnValue, params P[] excludeValues);

        bool Insert<DT>(DT data, string tableName, params string[] excludeColNames);

        int InsertGetInt<DT>(DT data, string tableName, params string[] excludeColNames);

        long InsertGetLong<DT>(DT data, string tableName, params string[] excludeColNames);

        bool Update<DT>(DT data, string tableName, string pkOrUniqueColName = "Id", params string[] excludeColNames);

        bool Upsert<DT>(DT data, string tableName, string pkOrUniqueColName = "Id", params string[] excludeColNames);

        bool UpSingle(string tableName, string columnName, object columnValue, object pkOrUniqueValue, string pkOrUniqueColName = "Id");

        int Delete<P>(string tableName, string columnName, params P[] columnValues); 

        #endregion

        DataTable GetDataTableByPager(int currentPage, int pageSize, string selColumns, string joinTableName, string whereStr, string orderbyStr, out long totalCount);

        KeyValuePair<DataTable,long> GetDataTableByPager(int currentPage, int pageSize, string selColumns, string joinTableName, string whereStr, string orderbyStr);
    }
}
